package com.tg.sieve_data.service.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tg.sieve_data.entity.ChannelDistributor;
import com.tg.sieve_data.entity.Region;
import com.tg.sieve_data.entity.RegionIssue;
import com.tg.sieve_data.entity.TgIssue;
import com.tg.sieve_data.entity.VisitRecord;
import com.tg.sieve_data.mapper.ChannelDistributorMapper;
import com.tg.sieve_data.mapper.RegionMapper;
import com.tg.sieve_data.mapper.RegionIssueMapper;
import com.tg.sieve_data.mapper.TgIssueMapper;
import com.tg.sieve_data.mapper.VisitRecordMapper;
import com.tg.sieve_data.service.TgIssueService;
import com.tg.sieve_data.utils.HttpContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class TgIssueServiceImpl extends ServiceImpl<TgIssueMapper, TgIssue>  implements TgIssueService {
    @Autowired
    private RegionMapper regionMapper;
    @Autowired
    private RegionIssueMapper regionIssueMapper;
    @Autowired
    private TgIssueMapper tgIssueMapper;
    @Autowired
    private VisitRecordMapper visitRecordMapper;
    @Autowired
    private ChannelDistributorMapper channelDistributorMapper;
    @Override
    public List<TgIssue> getByIp(String path) {
        long requestStartTime = System.currentTimeMillis();
        log.info("收到请求，开始时间: {}ms", requestStartTime);

        // 1. 根据path读取渠道列表
        ChannelDistributor channelDistributor = channelDistributorMapper.selectOne(
                new QueryWrapper<ChannelDistributor>().eq("path", path));

        // 如果没数据则使用path为"other"的默认渠道
        if (Objects.isNull(channelDistributor)) {
            log.info("未找到path={}的渠道，使用默认渠道other", path);
            channelDistributor = channelDistributorMapper.selectOne(
                    new QueryWrapper<ChannelDistributor>().eq("path", "other"));
             if (Objects.isNull(channelDistributor)) {
                 log.error("未找到默认渠道other，无法处理请求");
                 throw new RuntimeException("未找到默认渠道other，无法处理请求");
             }
        }

        // 2. 获取IP地址并解析地区代码
        String ip = HttpContextUtils.getIpAddress();
        log.info("页面获取到的ip地址 = {},path = {}", ip, path);
        // 3. 插入访问记录
        VisitRecord visitRecord = insertVisit(ip, path);

        String regionCode = "noip";
        int maxRetries = 3;
        int retryCount = 0;
        boolean success = false;
        while (!success && retryCount < maxRetries) {
            try {
                String body = HttpRequest.get("https://ipapi.co/" + ip + "/json/?key=AfbDgNdgtBSmchSVCme1cozupeuegTGEw12EyYcMKZnBL2NCZA")
                        .timeout(5000).execute().body();
                log.info("ip地址查询返回的body = {}", body);
                // 解析IP地址的地区代码
                JSONObject jsonObject = JSONObject.parseObject(body);
                regionCode = jsonObject.getString("country_code");
                log.info("ip地址解析后的regionCode = {}", regionCode);
                success = true;
            } catch (Exception e) {
                retryCount++;
                log.error("IP查询失败(第{}次尝试): {}", retryCount, e.getMessage(), e);

                if (retryCount < maxRetries) {
                    try {
                        // 休息2秒后重试
                        Thread.sleep(2000);
                        log.info("即将进行第{}次重试...", retryCount + 1);
                    } catch (InterruptedException ie) {
                        log.error("重试等待被中断: {}", ie.getMessage());
                        break;
                    }
                } else {
                    log.error("已达到最大重试次数({}次)，IP查询失败,ip = {}", maxRetries, ip);
                }
            }
        }


        // 4. 根据地区代码匹配数据库region表
        Region region = regionMapper.selectOne(new QueryWrapper<Region>().eq("code", regionCode));
        log.info("根据地区代码查询Region表，region = {}", region);
        if(Objects.isNull(region)){
            // 没有该地区代码，使用默认地区代码
            regionCode = "noip";
            region = regionMapper.selectOne(new QueryWrapper<Region>().eq("code", regionCode));
        }

        // 5. 根据地区代码获取联系人列表
        List<RegionIssue> regionIssues = regionIssueMapper.selectIssueIdByRegion(channelDistributor.getPath(), region.getCode());
        log.info("根据地区代码查询RegionIssue表，regionIssues = {}", regionIssues);
        if(CollUtil.isEmpty(regionIssues)){
            // 没有该地区代码的联系人，使用默认联系人
            regionIssues = regionIssueMapper.selectDefaultIssue(channelDistributor.getId());
        }

        // 6. 返回联系人列表
        List<Integer> issueIds = regionIssues.stream().map(RegionIssue::getIssueId).collect(Collectors.toList());
        List<TgIssue> tgIssues = tgIssueMapper.selectBatchIds(issueIds);
        Collections.shuffle(tgIssues);
        TgIssue res = tgIssues.get(0);
        List<TgIssue> tgIssueList = new ArrayList<>();
        tgIssueList.add(res);

        // 7. 记录访问记录
        log.info("记录访问记录，channelDistributor.id = {}, res.id = {}, ip = {}, regionCode = {}", channelDistributor.getId(), res.getId(), ip, regionCode);
//        updateVisit(channelDistributor.getId(), res.getId(), ip, regionCode);
        visitRecord.setIssueId(res.getId());
        visitRecord.setChannelId(channelDistributor.getId());
        visitRecord.setCountryCode(regionCode);
        visitRecord.setCreateTime(new Date());
        visitRecordMapper.updateById(visitRecord);

        return tgIssueList;
    }

    private VisitRecord insertVisit(String ip, String path){
        VisitRecord visitRecord = new VisitRecord();
        visitRecord.setIp(ip);
        visitRecord.setPath(path);
        visitRecord.setChannelId(0);
        visitRecordMapper.insert(visitRecord);
        return visitRecord;
    }

    @Override
    public Page<TgIssue> getAll(TgIssue tgIssue, Integer pageNum, Integer pageSize) {
        Page<TgIssue> page = new Page<>(pageNum, pageSize);
        List<TgIssue> records = baseMapper.getAll(page,tgIssue);
        records.stream().map(TgIssue::getRegion).collect(Collectors.toList());
        page.setRecords(records);
        return page;
    }

    @Override
    public List<TgIssue> getByRegionId(Integer regionId) {
        return baseMapper.getByRegionId(regionId);
    }
}
